package protocol

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"encoding/json"
)

/*------------------------- 消息格式 ---------------------------*/
const (
	DW_PUB = "DOW_PUB" // 下发公钥指令
	DW_FSE = "DW_FSE"  // 下发获取会话密钥失败指令
	DW_PWD = "DW_PWD"  // 下发通知客户发送口令指令
	DW_SUC = "DW_SUC"  // 下发通知客户认证成功指令

	UP_FUB = "UP_FUB" // 发送获取公钥失败指令
	UP_SEE = "UP_SEE" // 发送rsa公钥加密后的公钥指令
	UP_PWD = "UP_PWD" // 发送aes加密后的用户口令指令
	UP_HEA = "UP_HEA" // 客户的心跳包
	UP_CLO = "UP_CLO" // 客户请求断开连接
)

var (
	MSG_DW_FSE = &Message{DW_FSE, ""}
	MSG_DW_PWD = &Message{DW_PWD, ""}
	MSG_DW_SUC = &Message{DW_SUC, ""}

	MSG_UP_FUB = &Message{UP_FUB, ""}
	MSG_UP_HEA = &Message{UP_HEA, ""}
	MSG_UP_CLO = &Message{UP_CLO, ""}
)

var (
	DW_PUB_TIMES = 4 // 下发公钥的最多次数
	UP_SEE_TIMES = 4 // 收到会话密钥的最多次数
	UP_PWD_TIMES = 3 // 收到口令验证的最多次数
)

type Message struct {
	Type string `json:"type"` // 消息类型
	Data string `json:"data"` // 参数信息，如果有多个参数则形式如：param1=value&param2=value
}

func (e *Message) String() string {
	data, _ := json.Marshal(e)
	return string(data)
}

func (e *Message) JsonByte() []byte {
	data, _ := json.Marshal(e)
	return data
}

func PackMessageFromByte(mesJsonByte []byte) (*Message, error) {
	msg := &Message{}
	err := json.Unmarshal(mesJsonByte, msg)
	return msg, err
}

/*----------------------------处理粘包问题---------------------------*/
// Encode 将消息编码
func Encode(message []byte) ([]byte, error) {
	// 读取消息的长度，转换成int32类型（占4个字节）
	var length = int32(len(message))
	var pkg = new(bytes.Buffer)
	// 写入消息头
	err := binary.Write(pkg, binary.BigEndian, length)
	if err != nil {
		return nil, err
	}
	// 写入消息实体
	err = binary.Write(pkg, binary.BigEndian, message)
	if err != nil {
		return nil, err
	}
	return pkg.Bytes(), nil
}

// Decode 解码消息
func Decode(reader *bufio.Reader) ([]byte, error) {
	// 读取消息的长度
	lengthByte, _ := reader.Peek(4) 
    // 读取前4个字节的数据，但是不会取走字节
	lengthBuff := bytes.NewBuffer(lengthByte)
	var length int32
	err := binary.Read(lengthBuff, binary.BigEndian, &length)
	if err != nil {
		return []byte{}, err
	}
	// Buffered返回缓冲中现有的可读取的字节数。
	if int32(reader.Buffered()) < length+4 {
		return []byte{}, nil
	}
	// 读取真正的消息数据
	pack := make([]byte, int(4+length))
	_, err = reader.Read(pack)
	if err != nil {
		return []byte{}, err
	}
	return pack[4:], nil
}
